home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 20 / Cream of the Crop 20 (Terry Blount) (1996).iso / os2 / radius_2.zip / radiusd.c < prev    next >
C/C++ Source or Header  |  1996-06-04  |  46KB  |  1,814 lines

  1. /*
  2.  *
  3.  *    RADIUS
  4.  *    Remote Authentication Dial In User Service
  5.  *
  6.  *
  7.  *    Livingston Enterprises, Inc.
  8.  *    6920 Koll Center Parkway
  9.  *    Pleasanton, CA   94566
  10.  *
  11.  *    Copyright 1992 Livingston Enterprises, Inc.
  12.  *
  13.  *    Permission to use, copy, modify, and distribute this software for any
  14.  *    purpose and without fee is hereby granted, provided that this
  15.  *    copyright and permission notice appear on all copies and supporting
  16.  *    documentation, the name of Livingston Enterprises, Inc. not be used
  17.  *    in advertising or publicity pertaining to distribution of the
  18.  *    program without specific prior permission, and notice be given
  19.  *    in supporting documentation that copying and distribution is by
  20.  *    permission of Livingston Enterprises, Inc.   
  21.  *
  22.  *    Livingston Enterprises, Inc. makes no representations about
  23.  *    the suitability of this software for any purpose.  It is
  24.  *    provided "as is" without express or implied warranty.
  25.  *
  26.  */
  27.  
  28. /* don't look here for the version, run radiusd -v or look in version.c */
  29. static char sccsid[] =
  30. "@(#)radiusd.c    1.17 Copyright 1992 Livingston Enterprises Inc";
  31.  
  32. #include    <sys/types.h>
  33. #include    <sys/socket.h>
  34. #include    <sys/time.h>
  35. #include    <sys/file.h>
  36. #include    <netinet/in.h>
  37.  
  38. #include    <stdio.h>
  39. #include    <stdlib.h>
  40. #include    <netdb.h>
  41. #include    <fcntl.h>
  42. #include    <pwd.h>
  43. #include    <time.h>
  44. #include    <ctype.h>
  45. #include    <unistd.h>
  46. #include    <signal.h>
  47. #include    <errno.h>
  48. #include   <process.h>
  49. #include    <sys/wait.h>
  50. #include    <io.h>
  51.  
  52. #if !defined(NOSHADOW)
  53. /*#include    <shadow.h>*/
  54. #endif /* !NOSHADOW */
  55.  
  56. #include    "radius.h"
  57.  
  58. char        recv_buffer[4096];
  59. char        send_buffer[4096];
  60. char        *progname;
  61. int            sockfd;
  62. int            acctfd;
  63. int            debug_flag;
  64. int            spawn_flag;
  65. int            acct_flag;
  66. int            acct_pid;
  67. char        *radius_dir;
  68. char        *radacct_dir;
  69. #ifdef OS2
  70. char        radius_dir_hold[256];
  71. char        radacct_dir_hold[256]; 
  72. #endif
  73. UINT4        expiration_seconds;
  74. UINT4        warning_seconds;
  75. int    errno;
  76. static AUTH_REQ    *first_request;
  77.  
  78. void        sig_fatal();
  79. void        sig_hup();
  80. void        sig_cleanup();
  81. void        rad_passchange();
  82. void       usage(void);
  83. int        config_init();
  84. int        radrespond(AUTH_REQ    *authreq,int        activefd);
  85. int        rad_spawn_child(AUTH_REQ    *authreq,int        activefd);
  86. void         rad_authenticate(AUTH_REQ    *authreq,int        activefd);
  87. void        send_reject(AUTH_REQ    *authreq,char        *msg,int        activefd);
  88. int        set_expiration(VALUE_PAIR    *user_check,UINT4        expiration);
  89. void        send_pwack(AUTH_REQ    *authreq,int        activefd);
  90. int        calc_digest(u_char        *digest,AUTH_REQ    *authreq);
  91. int        pw_expired(UINT4    exptime);
  92. void        send_challenge(AUTH_REQ    *authreq,char *msg,char *state,int activefd);
  93. int        unix_pass(char    *name,char    *passwd);
  94. void        send_accept(AUTH_REQ *authreq,VALUE_PAIR *reply,char *msg,int activefd);
  95.  
  96. int
  97. main(argc, argv)
  98. int    argc;
  99. char    **argv;
  100. {
  101.     int            salen;
  102.     int            result;
  103.     struct        sockaddr    salocal;
  104.     struct        sockaddr    saremote;
  105.     struct        sockaddr_in    *sin;
  106.     struct        servent        *svp;
  107.     u_short        lport;
  108.     AUTH_REQ    *authreq;
  109.     AUTH_REQ    *radrecv();
  110.     char        argval;
  111.     int            t;
  112. #ifndef OS2
  113.     int            pid;
  114. #else
  115.    char        work_dir[256];
  116. #endif
  117.     int            cons;
  118.     fd_set        readfds;
  119.     int            status;
  120.     char *nargv[20];
  121.  
  122.     for ( t=0;t<argc ;t++ )
  123.        nargv[t] = argv[t];
  124.     nargv[t++]="-i";
  125.     nargv[t]=NULL;
  126.  
  127.     progname = *argv++;
  128.     argc--;
  129.  
  130.     debug_flag = 1;
  131.     acct_flag = 0;
  132.     spawn_flag = 1;
  133. #ifndef OS2
  134.     radacct_dir = RADACCT_DIR;
  135.     radius_dir = RADIUS_DIR;
  136. #else
  137.     sprintf(work_dir,"%s%s",getenv("ETC"),RADIUS_DIR);
  138.     _abspath(radius_dir_hold,work_dir,256);
  139.     sprintf(work_dir,"%s%s",getenv("ETC"),RADACCT_DIR);
  140.     _abspath(radacct_dir_hold,work_dir,256);
  141.     radius_dir = radius_dir_hold;
  142.    radacct_dir = radacct_dir_hold;
  143. #endif
  144.     signal(SIGHUP, sig_hup);
  145.     signal(SIGINT, sig_fatal);
  146.     signal(SIGQUIT, sig_fatal);
  147.     signal(SIGILL, sig_fatal);
  148. //    signal(SIGTRAP, sig_fatal);
  149. //    signal(SIGIOT, sig_fatal);
  150.     signal(SIGFPE, sig_fatal);
  151.     signal(SIGTERM, sig_fatal);
  152.     signal(SIGCHLD, sig_cleanup);
  153.  
  154.     while(argc) {
  155.  
  156.         if(**argv != '-') {
  157.             usage();
  158.         }
  159.  
  160.         argval = *(*argv + 1);
  161.         argc--;
  162.         argv++;
  163.  
  164.         switch(argval) {
  165.  
  166.         case 'a':
  167.             if(argc == 0) {
  168.                 usage();
  169.             }
  170.             radacct_dir = *argv;
  171.            argc--;
  172.             argv++;
  173.             DEBUG("diff acct dir\n");
  174.              break;
  175.         
  176.         case 'd':
  177.             if(argc == 0) {
  178.                 usage();
  179.             }
  180.             radius_dir = *argv;
  181.             argc--;
  182.             argv++;
  183.              DEBUG("diff radius dir\n");
  184.             break;
  185.         
  186.         case 's':    /* Single process mode */
  187.            spawn_flag = 0;
  188.            acct_flag = 1;
  189.            DEBUG("Single process mode\n");
  190.            break;
  191.  
  192.         case 'v':
  193.             version();
  194.             break;
  195.  
  196.         case 'x':
  197.             debug_flag = 1;
  198.              DEBUG("Debug mode\n");
  199.             break;
  200.         
  201.         case 'i':
  202.             acct_flag = 1;
  203.             sockfd = -1;
  204.              DEBUG("Accounting spawn process\n");
  205.             break;
  206.  
  207.         default:
  208.             usage();
  209.             break;
  210.         }
  211.     }
  212.  
  213.     /* Initialize the dictionary */
  214.     if(dict_init() != 0) {
  215.         exit(-1);
  216.     }
  217.     DEBUG("dict_init complete\n");
  218.     /* Initialize Configuration Values */
  219.     if(config_init() != 0) {
  220.         exit(-1);
  221.     }
  222.     DEBUG("config_init complete\n");
  223.  
  224.     if ( sockfd != -1 ) {
  225.         svp = getservbyname ("radius", "udp");
  226.         if (svp == (struct servent *) 0) {
  227.             fprintf (stderr, "%s: No such service: radius/udp\n", progname);
  228.             exit(-1);
  229.         }
  230.         lport = (u_short) svp->s_port;
  231.  
  232.         sockfd = socket (AF_INET, SOCK_DGRAM, 0);
  233.         if (sockfd < 0) {
  234.             (void) perror ("auth socket");
  235.             exit(-1);
  236.         }
  237.  
  238.         sin = (struct sockaddr_in *) & salocal;
  239.         memset ((char *) sin, '\0', sizeof (salocal));
  240.         sin->sin_family = AF_INET;
  241.         sin->sin_addr.s_addr = INADDR_ANY;
  242.         sin->sin_port = lport;
  243.  
  244.         result = bind (sockfd, & salocal, sizeof (*sin));
  245.  
  246.         if (result < 0) {
  247.             (void) perror ("auth bind");
  248.             exit(-1);
  249.         }
  250.         DEBUG("Author socket complete\n");
  251.     }
  252.     /*
  253.      * Open Accounting Socket.
  254.      */
  255.     svp = getservbyname ("radacct", "udp");
  256.     if (svp == (struct servent *) 0) {
  257.        fprintf (stderr, "%s: No such service: %s/%s\n",
  258.           progname, "radacct", "udp");
  259.        exit(-1);
  260.     }
  261.     //do not delete:  lport = htons(ntohs(lport) +1);
  262.     lport = (u_short) svp->s_port;
  263.     acctfd = socket (AF_INET, SOCK_DGRAM, 0);
  264.     if (acctfd < 0) {
  265.        (void) perror ("acct socket");
  266.        exit(-1);
  267.     }
  268.  
  269.     sin = (struct sockaddr_in *) & salocal;
  270.     memset ((char *) sin, '\0', sizeof (salocal));
  271.     sin->sin_family = AF_INET;
  272.     sin->sin_addr.s_addr = INADDR_ANY;
  273.     sin->sin_port = lport;
  274.  
  275.     result = bind (acctfd, & salocal, sizeof (*sin));
  276.  
  277.     if (result < 0) {
  278.        (void) perror ("acct bind");
  279.        exit(-1);
  280.     }
  281.     DEBUG("Radacct socket complete\n");
  282.     /*
  283.      *    Disconnect from session
  284.      */
  285. #ifndef OS2
  286.     if(debug_flag == 0) {
  287.         pid = fork();
  288.         if(pid < 0) {
  289.             fprintf(stderr, "%s: Couldn't fork\n", progname);
  290.             exit(-1);
  291.         }
  292.         if(pid > 0) {
  293.             exit(0);
  294.         }
  295.     }
  296. #endif
  297.  
  298.     /*
  299.      *    Disconnect from tty
  300.      */
  301.     for (t = 32; t >= 3; t--) {
  302.         if(t != sockfd && t != acctfd) {
  303.             close(t);
  304.         }
  305.     }
  306.  
  307. #if !defined(M_UNIX)
  308.     /*
  309.      * Open system console as stderr
  310.      */
  311.     cons = open("/dev/console", O_WRONLY | O_NOCTTY);
  312.     if(cons != 2) {
  313.         dup2(cons, 2);
  314.         close(cons);
  315.     }
  316. #endif
  317.     /*
  318.      * If we are able to spawn processes, we will start a child
  319.      * to listen for Accounting requests.  If not, we will 
  320.      * listen for them ourself.
  321.      */
  322.     if( spawn_flag && !acct_flag ) {
  323. #ifndef OS2
  324.         acct_pid = fork();
  325. #else
  326.         acct_pid = spawnv(P_NOWAIT,nargv[0],nargv); 
  327. /*       acct_pid = spawnl(P_NOWAIT,argv[0],argv[0],"-x","-i",(char *)0); */
  328. #endif
  329.         DEBUG("Accounting Spawned\n");
  330.          if(acct_pid < 0) {
  331.             fprintf(stderr, "%s: Couldn't fork\n", progname);
  332.             exit(-1);
  333.         }
  334.         if(acct_pid > 0) {
  335.             close(acctfd);
  336.             acctfd = -1;
  337.         }
  338.         else {
  339.             if ( sockfd != -1 )
  340.                close(sockfd);
  341.             sockfd = -1;
  342.         }
  343.     }
  344.         
  345.     /*
  346.      *    Receive user requests
  347.      */
  348.     sin = (struct sockaddr_in *) & saremote;
  349.     DEBUG("Ready to receive user requests\n");
  350.     for(;;) {
  351.        FD_ZERO(&readfds);
  352.        if(sockfd >= 0) {
  353.           FD_SET(sockfd, &readfds);
  354.        }
  355.        if(acctfd >= 0) {
  356.           FD_SET(acctfd, &readfds);
  357.        }
  358.  
  359.        status = select(32, &readfds, NULL, NULL, NULL);
  360.  
  361.        if(status == -1) {
  362.           if (errno == EINTR)
  363.